package com.hujun.common.time.core;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hujun.common.time.common.DateTimeUtils;
import com.hujun.common.time.common.TimerConstant;
import com.hujun.common.time.config.JobConfig;
import com.hujun.common.time.config.SchedulerConfig;
import com.hujun.common.time.config.TriggerConfig;

public class ConfigFactory {
	public static volatile SchedulerConfig schedulerConfig;
	private static final Logger log = LoggerFactory
			.getLogger(ConfigFactory.class);


	public static SchedulerConfig getConfig() throws Exception {
		if (null == schedulerConfig) {
			synchronized (ConfigFactory.class) {
				if (null == schedulerConfig) {
					schedulerConfig = new SchedulerConfig();
					init();
				}
			}
		}
		return schedulerConfig;
	}

	public static void init() throws Exception {
		SAXReader reader = new SAXReader();
		Map<String, JobConfig> jobsMap = new HashMap<String, JobConfig>();
		Map<String, TriggerConfig> triggersMap = new HashMap<String, TriggerConfig>();
		try {
			Document doc = reader.read(ConfigFactory.class.getResourceAsStream("/timer.xml"));
			Node root = doc.selectSingleNode("/jobs");
			List jobs = root.selectNodes("job"); // 获取所有job
			for (Object o : jobs) {
				Element e = (Element) o;
				String show = e.attributeValue("id");// jobName
				if (show == null || jobsMap.containsKey(show)) {
					throw new IllegalArgumentException(
							"jobName must not be null or repetitive");
				}
				String className = e.attributeValue("class");// job对应的className
				if (className == null) {
					throw new IllegalArgumentException(
							"className must be not  null");
				}
				List properties = e.selectNodes("property[@name='trigger']");
				if (properties == null || properties.size() > 1) {
					throw new IllegalArgumentException(
							"trigger must be not null and one job must one trigger!");
				}
				Element property = (Element) properties.get(0);
				String triggerName = property.attributeValue("ref");// job对应的触发器ID
				if (triggerName == null) {
					throw new IllegalArgumentException(
							"triggerName must be not null");
				}
				JobConfig jobConfig = new JobConfig();
				jobConfig.setJobName(show);
				jobConfig.setClassName(className);
				jobConfig.setTriggerName(triggerName);
				jobsMap.put(show, jobConfig);// 用map保存job的配置信息
				List triggers = root.selectNodes("trigger[@id='"
						+ triggerName.trim() + "']");
				if (triggers == null || triggers.size() > 1) {
					throw new IllegalArgumentException(
							"trigger Id must be only one");
				}
				TriggerConfig config = fillTriggersMap((Element)triggers.get(0));
				if(!triggersMap.containsKey(triggerName)){
					triggersMap.put(triggerName, config);
				}
			}
			schedulerConfig.setJobs(jobsMap);
			schedulerConfig.setTriggers(triggersMap);
		} catch (Exception e) {
			log.error("init config error!");
			throw e;
		}
	}

	private static TriggerConfig fillTriggersMap(Element trigger)
			throws Exception {
		String triggerType = trigger
				.attributeValue("type");
		if (triggerType == null) {
			throw new IllegalArgumentException(
					"trigger type must be not null");
		}
		List triggerProperties = trigger
				.selectNodes("property[@name and @value]");
		Class simpleTriggerConfig = null;
		Object o = null;
		if (triggerType.equals(TimerConstant.TRIGGER_SIMPLE)) {
			try {
				simpleTriggerConfig = Class
						.forName("com.hujun.common.time.config.SimpleTriggerConfig");
				o = simpleTriggerConfig.newInstance();
			} catch (Exception e) {
				log.error("com.hujun.common.time.config.SimpleTriggerConfig not found");
				throw e;
			}
			
		}else if(triggerType.equals(TimerConstant.TRIGGER_CRON)){
			try {
				simpleTriggerConfig = Class
						.forName("com.hujun.common.time.config.CronTriggerConfig");
				o = simpleTriggerConfig.newInstance();
			} catch (Exception e) {
				log.error("com.hujun.common.time.config.CronTriggerConfig not found");
				throw e;
			}
		}
		Field fieldName = simpleTriggerConfig.getSuperclass().getDeclaredField("triggerName");
		fieldName.setAccessible(true);
		fieldName.set(o, trigger.attributeValue("id"));
		Field fieldType = simpleTriggerConfig.getSuperclass().getDeclaredField("type");
		fieldType.setAccessible(true);
		fieldType.set(o, triggerType);
		for (Object t : triggerProperties) {
			Element tp = (Element)t;
			String name = tp.attributeValue("name");
			String value = tp.attributeValue("value");
			if (name == null || value == null) {
				throw new IllegalArgumentException(
						"name and  value must be not null");
			}
			
			Field field = simpleTriggerConfig.getDeclaredField(name);
			System.out.println(field.getType());
			field.setAccessible(true);
			if(field.getType().getName().equals(long.class.getName())){
				field.set(o, Long.valueOf(value));
			}else if(field.getType().getName().equals(int.class.getName())){
				field.set(o, Integer.valueOf(value));
			}else if(field.getType().getName().equals(java.util.Date.class.getName())){
				field.set(o, DateTimeUtils.parseToDate(value, "yyyy-MM-dd HH:mm:ss"));
			}else{
				field.set(o, value);
			}
		}
		return (TriggerConfig)o;
	}
	public static void main(String[] args) {
		try {
			getConfig();
			System.out.println(schedulerConfig.getJobs());
			System.out.println(schedulerConfig.getTriggers());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
